{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## try & except 块"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "写代码的时候，出现错误必不可免，即使代码没有问题，也可能遇到别的问题。\n",
    "\n",
    "看下面这段代码：\n",
    "\n",
    "```python \n",
    "import math\n",
    "\n",
    "while True:\n",
    "    text = raw_input('> ')\n",
    "    if text[0] == 'q':\n",
    "        break\n",
    "    x = float(text)\n",
    "    y = math.log10(x)\n",
    "    print \"log10({0}) = {1}\".format(x, y)\n",
    "```\n",
    "\n",
    "这段代码接收命令行的输入，当输入为数字时，计算它的对数并输出，直到输入值为 `q` 为止。\n",
    "\n",
    "乍看没什么问题，然而当我们输入0或者负数时："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> -1\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "math domain error",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-1-ceb8cf66641b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      6\u001b[0m         \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      7\u001b[0m     \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m     \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlog10\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      9\u001b[0m     \u001b[1;32mprint\u001b[0m \u001b[1;34m\"log10({0}) = {1}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mValueError\u001b[0m: math domain error"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    text = raw_input('> ')\n",
    "    if text[0] == 'q':\n",
    "        break\n",
    "    x = float(text)\n",
    "    y = math.log10(x)\n",
    "    print \"log10({0}) = {1}\".format(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`log10` 函数会报错，因为不能接受非正值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一旦报错，程序就会停止执行，如果不希望程序停止执行，那么我们可以添加一对 `try & except`： "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = math.log10(x)\n",
    "        print \"log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\"\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一旦 `try` 块中的内容出现了异常，那么 `try` 块后面的内容会被忽略，**Python**会寻找 `except` 里面有没有对应的内容，如果找到，就执行对应的块，没有则抛出这个异常。\n",
    "\n",
    "在上面的例子中，`try` 抛出的是 `ValueError`，`except` 中有对应的内容，所以这个异常被 `except` 捕捉到，程序可以继续执行："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> -1\n",
      "the value must be greater than 0\n",
      "> 0\n",
      "the value must be greater than 0\n",
      "> 1\n",
      "log10(1.0) = 0.0\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = math.log10(x)\n",
    "        print \"log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 捕捉不同的错误类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "``` python\n",
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\"\n",
    "```\n",
    "\n",
    "假设我们将这里的 `y` 更改为 `1 / math.log10(x)`，此时输入 `1`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "float division by zero",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mZeroDivisionError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-3-7607f1ae6af9>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      7\u001b[0m             \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      8\u001b[0m         \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 9\u001b[1;33m         \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m/\u001b[0m \u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlog10\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     10\u001b[0m         \u001b[1;32mprint\u001b[0m \u001b[1;34m\"log10({0}) = {1}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     11\u001b[0m     \u001b[1;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mZeroDivisionError\u001b[0m: float division by zero"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因为我们的 `except` 里面并没有 `ZeroDivisionError`，所以会抛出这个异常，我们可以通过两种方式解决这个问题："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 捕捉所有异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将`except` 的值改成 `Exception` 类，来捕获所有的异常。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n",
      "invalid value\n",
      "> 0\n",
      "invalid value\n",
      "> -1\n",
      "invalid value\n",
      "> 2\n",
      "1 / log10(2.0) = 3.32192809489\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"1 / log10({0}) = {1}\".format(x, y)\n",
    "    except Exception:\n",
    "        print \"invalid value\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 指定特定值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里，我们把 `ZeroDivisionError` 加入 `except` 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n",
      "invalid value\n",
      "> -1\n",
      "invalid value\n",
      "> 0\n",
      "invalid value\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"1 / log10({0}) = {1}\".format(x, y)\n",
    "    except (ValueError, ZeroDivisionError):\n",
    "        print \"invalid value\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "或者另加处理："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n",
      "the value must not be 1\n",
      "> -1\n",
      "the value must be greater than 0\n",
      "> 0\n",
      "the value must be greater than 0\n",
      "> 2\n",
      "1 / log10(2.0) = 3.32192809489\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"1 / log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\"\n",
    "    except ZeroDivisionError:\n",
    "        print \"the value must not be 1\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "事实上,我们还可以将这两种方式结合起来,用 `Exception` 来捕捉其他的错误："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n",
      "the value must not be 1\n",
      "> -1\n",
      "the value must be greater than 0\n",
      "> 0\n",
      "the value must be greater than 0\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"1 / log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError:\n",
    "        print \"the value must be greater than 0\"\n",
    "    except ZeroDivisionError:\n",
    "        print \"the value must not be 1\"\n",
    "    except Exception:\n",
    "        print \"unexpected error\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 得到异常的具体信息"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在上面的例子中，当我们输入不能转换为浮点数的字符串时，它输出的是 `the value must be greater than 0`，这并没有反映出实际情况。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "could not convert string to float: a",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-99859da4e72c>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m: could not convert string to float: a"
     ]
    }
   ],
   "source": [
    "float('a')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为了得到异常的具体信息，我们将这个 `ValueError` 具现化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 1\n",
      "the value must not be 1\n",
      "> -1\n",
      "the value must be greater than 0\n",
      "> aa\n",
      "could not convert 'aa' to float\n",
      "> q\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        text = raw_input('> ')\n",
    "        if text[0] == 'q':\n",
    "            break\n",
    "        x = float(text)\n",
    "        y = 1 / math.log10(x)\n",
    "        print \"1 / log10({0}) = {1}\".format(x, y)\n",
    "    except ValueError as exc:\n",
    "        if exc.message == \"math domain error\":\n",
    "            print \"the value must be greater than 0\"\n",
    "        else:\n",
    "            print \"could not convert '%s' to float\" % text\n",
    "    except ZeroDivisionError:\n",
    "        print \"the value must not be 1\"\n",
    "    except Exception as exc:\n",
    "        print \"unexpected error:\", exc.message"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同时，我们也将捕获的其他异常的信息显示出来。\n",
    "\n",
    "这里，`exc.message` 显示的内容是异常对应的说明，例如\n",
    "\n",
    "    ValueError: could not convert string to float: a\n",
    "\n",
    "对应的 `message` 是 \n",
    "\n",
    "    could not convert string to float: a\n",
    "\n",
    "当我们使用 `except Exception` 时，会捕获所有的 `Exception` 和它派生出来的子类，但不是所有的异常都是从 `Exception` 类派生出来的，可能会出现一些不能捕获的情况，因此，更加一般的做法是使用这样的形式：\n",
    "\n",
    "```python\n",
    "try:\n",
    "    pass\n",
    "except:\n",
    "    pass\n",
    "```\n",
    "\n",
    "这样不指定异常的类型会捕获所有的异常，但是这样的形式并不推荐。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 自定义异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "异常是标准库中的类，这意味着我们可以自定义异常类："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class CommandError(ValueError):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里我们定义了一个继承自 `ValueError` 的异常类，异常类一般接收一个字符串作为输入，并把这个字符串当作异常信息，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> bad command\n"
     ]
    },
    {
     "ename": "CommandError",
     "evalue": "Invalid commmand: bad command",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mCommandError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-11-0e1f81a1136d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[0mcommand\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mraw_input\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'> '\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[0mcommand\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlower\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mvalid_commands\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m         \u001b[1;32mraise\u001b[0m \u001b[0mCommandError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Invalid commmand: %s'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0mcommand\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mCommandError\u001b[0m: Invalid commmand: bad command"
     ]
    }
   ],
   "source": [
    "valid_commands = {'start', 'stop', 'pause'}\n",
    "\n",
    "while True:\n",
    "    command = raw_input('> ')\n",
    "    if command.lower() not in valid_commands:\n",
    "        raise CommandError('Invalid commmand: %s' % command)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们使用 `raise` 关键词来抛出异常。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以使用 `try/except` 块来捕捉这个异常："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "``` python\n",
    "valid_commands = {'start', 'stop', 'pause'}\n",
    "\n",
    "while True:\n",
    "    command = raw_input('> ')\n",
    "    try:\n",
    "        if command.lower() not in valid_commands:\n",
    "            raise CommandError('Invalid commmand: %s' % command)\n",
    "    except CommandError:\n",
    "        print 'Bad command string: \"%s\"' % command\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于 `CommandError` 继承自 `ValueError`，我们也可以使用 `except ValueError` 来捕获这个异常。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## finally"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "try/catch 块还有一个可选的关键词 finally。\n",
    "\n",
    "不管 try 块有没有异常， finally 块的内容总是会被执行，而且会在抛出异常前执行，因此可以用来作为安全保证，比如确保打开的文件被关闭。。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "finally was called.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print 1\n",
    "finally:\n",
    "    print 'finally was called.'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在抛出异常前执行："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "finally was called.\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "integer division or modulo by zero",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mZeroDivisionError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-13-87ecdf8b9265>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m     \u001b[1;32mprint\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      3\u001b[0m \u001b[1;32mfinally\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[1;32mprint\u001b[0m \u001b[1;34m'finally was called.'\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print 1 / 0\n",
    "finally:\n",
    "    print 'finally was called.'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果异常被捕获了，在最后执行："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "divide by 0.\n",
      "finally was called.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print 1 / 0\n",
    "except ZeroDivisionError:\n",
    "    print 'divide by 0.'\n",
    "finally:\n",
    "    print 'finally was called.'"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
